#include "thread.hpp"

ThreadPool::ThreadPool(size_t thread_count) : stop(false) {
    for (size_t i = 0; i < thread_count; ++i) 
    {
        workers.emplace_back(&ThreadPool::worker_loop, this);
    }
}

ThreadPool::~ThreadPool() {
    stop.store(true);
    cv.notify_all();
    for (auto& t :workers) {
        if (t.joinable()) t.join();
    }
}

void ThreadPool::enqueue(function<void()> task) {
    {
        lock_guard<mutex> lock(mtx);
        tasks.push(move(task));
    }
    cv.notify_one();
}

void ThreadPool::worker_loop() {
    while(true) {
        function<void()> task;
        {
            unique_lock<mutex> lock(mtx);
            cv.wait(lock, [this] () { return stop || !tasks.empty(); });
            if(stop && tasks.empty()) return;
            task = move(tasks.front());
            tasks.pop();
        }
        task();
    }
}
